﻿using IMModel.Domain;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using IMModel.Domain.Common;
using System.Data.Linq;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using IMModel;
using System.IO;
using System.Text;
using Microsoft.Office.Interop.Excel;


namespace IMTests
{
    /// <summary>
    ///This is a test class for TermTest and is intended
    ///to contain all TermTest Unit Tests
    ///</summary>
    [TestClass()]
    public class Paretto
    {
        //Term T1, T2;
        IMDataDataContext DB = new IMDataDataContext(
            "Data Source=ugtudb;Initial Catalog=IndexMark;Integrated Security=True");



        [TestMethod()]
        public void GetStat()
        {
            Distribution();

            //System.Windows.Forms.Clipboard.SetText(
            //    Distribution("Доклад на научном семинаре/научной конференции") +
            //    Distribution("Доклад студента на научной конференции  с указанием в программе конференции его научного руководителя")+
            //    Distribution("Количество читаемых дисциплин")+
            //    Distribution("Продукция  учебно-методического характера ")+
            //    Distribution("Распределение учебной нагрузки по категориям обучаемых ")+
            //    Distribution("Статья  научного характера")+
            //    Distribution("Статья научно-методического характера"));


            // выполнение 3-7 минут
            //Distribution();

            // выполнение 2-4 минут
            //AvgInput();

            // не работает, если не работает расчёт индексов
            //Indexes();
        }

        private void Distribution()
        {
            var s = new StringBuilder();

            //foreach (var t in DB.Terms)
            {
                var t = DB.Terms.Single(x=>x.IDTerm == 10);
                int skip = 0, count = 0;
                var ls = new List<string>();
                var lc = new List<string>();

                foreach (var ct in t.CharacteristicTerms)
                {
                    var rr = t.Respondents.Select(x =>
                        new
                        {
                            x.Person.FullName,
                            val = x.Answers.Where(a =>
                                a.CharacteristicTerm == ct && a.LastAnswer).Sum(a => a.Value)
                        }).ToList();

                    // настройка пропусков 10 и 100
                    //if (rr.Count(x => x.val > 0) < 10 || rr.Sum(x => x.val) < 100)
                    //{
                    //    ++skip;
                    //    ls.Add(ct.Characteristic.Name);
                    //    continue;
                    //}
                    ++count;
                    s.AppendLine(ct.Characteristic.Name);
                    lc.Add(ct.Characteristic.Name);
                    rr = rr.OrderByDescending(x => x.val).ToList();

                    foreach (var r in rr)
                    {
                        s.Append(r.FullName);
                        s.Append("\t");
                    }
                    s.AppendLine();
                    foreach (var r in rr)
                    {
                        s.Append(r.val);
                        s.Append("\t");
                    }

                    //Паретто
                    //double d = 0;
                    //double m1 = rr.Sum(x => x.val);
                    //double m2 = rr.Count;
                    //double n = 0;
                    //s.AppendLine();
                    //foreach (var r in rr)
                    //{
                    //    d += r.val / m1;
                    //    s.Append(d);
                    //    s.Append("\t");
                    //}
                    //s.AppendLine();
                    //foreach (var r in rr)
                    //{
                    //    s.Append(++n / m2);
                    //    s.Append("\t");
                    //}
                    s.AppendLine();
                    s.AppendLine();
                }

                s.AppendFormat("\n\nРаспределение значений показателей в периоде {0}, учтено {1}, пропущено {2}, всего {3}\n\n", t.Years(), count, skip, t.CharacteristicTerms.Count);
                s.AppendFormat("Учтено:\n{0}\nПропущено:\n{1}\n\n\n\n",
                    string.Join("; ", lc), string.Join("; ", ls));
            }

            Show(s);
            //File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), s.ToString());
        }

        private string Distribution(string ch)
        {
            var s = new StringBuilder();
            string p = "P = ";

            foreach (var t in DB.Terms)
            {
                int skip = 0, count = 0;
                var ls = new List<string>();
                var lc = new List<string>();

                foreach (var ct in t.CharacteristicTerms.Where(x=>x.Characteristic.Name == ch))
                {
                    var rr = t.Respondents.Select(x =>
                        new
                        {
                            x.Person.FullName,
                            val = x.Answers.Where(a =>
                                a.CharacteristicTerm == ct && a.LastAnswer).Sum(a => a.Value)
                        }).ToList();

                    ++count;
                    s.AppendLine(ct.Characteristic.Name);
                    lc.Add(ct.Characteristic.Name);
                    rr = rr.OrderByDescending(x => x.val).ToList();

                    foreach (var r in rr)
                    {
                        s.Append(r.FullName);
                        s.Append("\t");
                    }
                    s.AppendLine();
                    foreach (var r in rr)
                    {
                        s.Append(r.val);
                        s.Append("\t");
                    }

                    //Паретто
                    double d = 0, half = 0;
                    double m1 = rr.Sum(x => x.val);
                    double m2 = rr.Count;
                    double n = 0;
                    s.AppendLine();
                    foreach (var r in rr)
                    {
                        d += r.val / m1;

                        half += r.val / m1;
                        ++n;
                        if (half > 0.5) 
                        {
                            p += d + "/" + n / m2;
                            half = 0;
                        }

                        s.Append(d);
                        s.Append("\t");
                    }
                    s.AppendLine();

                    n=0;
                    foreach (var r in rr)
                    {
                        s.Append(++n / m2);
                        s.Append("\t");
                    }
                    s.AppendLine();
                    s.AppendLine();
                }

                s.AppendFormat("\nРаспределение значений показателей в периоде {0}, учтено {1}, пропущено {2}, всего {3}, {4}\n\n", t.Years(), count, skip, t.CharacteristicTerms.Count, p);
            }

            return s.ToString();
            //File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), s.ToString());
        }


        private void AvgInput()
        {
            StringBuilder s = new StringBuilder();
            s.AppendLine("Среднее количество введённых показателей по годам и должностям (количество ППС, показателей на человека, результатов на человека)");

            var st = "Период\tВсего";
            var pos = DB.Positions.Where(x => x.Jobs.Count > 1).OrderByDescending(x => x.Order).ToArray();
            foreach (var p in pos) st += "\t" + p.Name;

            s.Append("\n\nКоличество ППС\n" + st);
            foreach (var t in DB.Terms)
            {
                if (!t.Respondents.Any()) continue;
                //Период
                s.AppendFormat("\n{0}/{1}\t", t.Start.Year, t.Stop.Year);

                //Всего ППС
                s.Append(t.Respondents.Count() + "\t");
                //По должностям Количество ППС
                foreach (var p in pos)
                {
                    var dd = t.Respondents.Where(x => x.Job.Position == p);
                    s.Append(dd.Count() + "\t");
                }
            }

            s.Append("\n\nПоказателей на человека\n" + st);
            foreach (var t in DB.Terms)
            {
                if (!t.Respondents.Any()) continue;
                //Период
                s.AppendFormat("\n{0}/{1}\t", t.Start.Year, t.Stop.Year);
                //Показателей на человека
                s.Append(t.Respondents.Average(r => r.Answers.Select(x =>
                    x.CharacteristicTerm.IDCharacteristic).Distinct().Count()) + "\t");
                //По должностям Показателей на человека
                foreach (var p in pos)
                {
                    var dd = t.Respondents.Where(x => x.Job.Position == p);
                    s.Append((dd.Any() ? dd.Average(r => r.Answers.Select(x =>
                        x.CharacteristicTerm.IDCharacteristic).Distinct().Count()) : 0) + "\t");
                }
            }

            s.Append("\n\nРезультатов на человека\n" + st);
            foreach (var t in DB.Terms)
            {
                if (!t.Respondents.Any()) continue;
                //Период
                s.AppendFormat("\n{0}/{1}\t", t.Start.Year, t.Stop.Year);
                //Результатов на человека
                s.Append(t.Respondents.Average(r => r.Answers.Count()) + "\t");
                //По должностям Результатов на человека
                foreach (var p in pos)
                {
                    var dd = t.Respondents.Where(x => x.Job.Position == p);
                    s.Append((dd.Any() ? dd.Average(r => r.Answers.Count) : 0) + "\t");
                }
            }

            s.Append("\n\nРезультатов на человека2\n" + st);
            foreach (var t in DB.Terms)
            {
                if (!t.Respondents.Any()) continue;
                //Период
                s.AppendFormat("\n{0}/{1}\t", t.Start.Year, t.Stop.Year);
                //Результатов на человека
                s.Append(t.Respondents.Average(r => r.Answers.Where(x =>
                    x.LastAnswer).Sum(x => x.Volume)) + "\t");
                //По должностям Результатов на человека
                foreach (var p in pos)
                {
                    var dd = t.Respondents.Where(x => x.Job.Position == p);
                    s.Append((dd.Any() ? dd.Average(r =>
                        r.Answers.Where(x => x.LastAnswer).Sum(x => x.Volume)) : 0) + "\t");
                }
            }
            Show(s);
        }

        void Show(StringBuilder sb)
        {
            System.Windows.Forms.Clipboard.SetText(sb.ToString());
        }

        private void Indexes()
        {
            var s = new StringBuilder();

            foreach (var t in DB.Terms)
            {
                try
                {
                    s.AppendLine(t.Years() + "\t" + string.Join("\t", t.Indexes));
                }
                catch { }
            }
            Show(s);
        }

        #region Excel
        private void DistributionToExcel(Term t)
        {
            Application xlApp;
            Workbook xlWorkBook;
            Worksheet xlWorkSheet;

            xlApp = new Application();
            xlWorkBook = xlApp.Workbooks.Add();

            xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.get_Item(1);
            //var ws = xlWorkBook.Worksheets.Add();
            int nr = 1, nc = 1;

            foreach (var ct in t.CharacteristicTerms)
            {
                xlWorkSheet.Cells[nr, 1] = ct.Characteristic.Name;
                nr += 4;
                nc = 1;
                foreach (var r in t.Respondents)
                {
                    var v = r.Answers.Where(x => x.CharacteristicTerm == ct).Sum(x => x.Value);
                    xlWorkSheet.Cells[nr + 1, ++nc] = v;
                    xlWorkSheet.Cells[nr + 2, nc] = r.Person.FullName;
                }
            }

            xlApp.Visible = true;

            //xlWorkBook.SaveAs("csharp-Excel.xls", XlFileFormat.xlWorkbookNormal);
            //xlWorkBook.Close(true);
            //xlApp.Quit();

            //releaseObject(xlWorkSheet);
            //releaseObject(xlWorkBook);
            //releaseObject(xlApp);
        }

        private void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                System.Windows.Forms.MessageBox.Show(
                    "Exception Occured while releasing object " + ex);
            }
            finally
            {
                GC.Collect();
            }
        }
        #endregion
    }
}